package com.jse.mvc;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.entity.Record;
import org.nutz.http.Http;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.View;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Fail;
import org.nutz.mvc.annotation.Filters;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import org.nutz.weixin.at.impl.DaoAccessTokenStore;
import org.nutz.weixin.impl.WxApi2Impl;
import org.nutz.weixin.spi.WxApi2;
import org.nutz.weixin.spi.WxHandler;
import org.nutz.weixin.spi.WxResp;
import org.nutz.weixin.util.Wxs;

import com.vdurmont.emoji.EmojiParser;

/**
 * Created by wizzer on 2016/8/6.
 */
@IocBean
@At("/wechat")
public class WechatAction {
	private static final Log log = Logs.get();
	@Inject
	Dao dao;
	@Inject("conf")
	PropertiesProxy conf;
	@Inject
	WxHandler wxHandler;

	public WechatAction() {
		Wxs.enableDevMode(); // 开启debug模式,这样就会把接收和发送的内容统统打印,方便查看
	}

	@At({ "/api", "/api/?" })
	@Fail("http:200")
	public View msgIn(String key, HttpServletRequest req) throws IOException {
		return Wxs.handle(wxHandler, req, key);
	}

	@At("/?/oauth")
	@Ok("re")
	@Filters
	public String oauth(String wxid, @Param(value = "goto", df = "/") String goto_url, HttpServletRequest req,
			HttpSession session) throws Exception {
		session.setAttribute("wechat_goto_url", goto_url);
		if (!Strings.isBlank(wxid)) {
			Record config = dao.fetch("wx_config", Cnd.where("id", "=", wxid));
			String back_url = "http://" + conf.get("host") + "/public/wx/wechat/" + wxid + "/back";
			String redirect_uri = URLEncoder.encode(back_url, "utf-8");
			log.debug("redirect_uri::" + redirect_uri);
			String state = "wechat";
			String scope = "snsapi_base";
			String oauth_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + config.getString("appid")
					+ "&redirect_uri=" + redirect_uri + "&response_type=code&scope=" + scope + "&state=" + state
					+ "#wechat_redirect";
			return "redirect:" + oauth_url;
		} else {
			return "redirect:" + goto_url;
		}
	}

	/**
	 * 检查用户 注册或登陆
	 * 
	 * @param wxid
	 *            配置的微信id
	 * @param code
	 * @param req
	 * @param session
	 * @return
	 * @throws Exception
	 */
	@At("/?/check")
	@Ok("re")
	@Filters
	public String check(String wxid, @Param("code") String code, HttpServletRequest req, HttpSession session)
			throws Exception {
		String wechat_goto_url = Strings.sNull(session.getAttribute("wechat_goto_url"));
		Record config = dao.fetch("wx_config", Cnd.where("id", "=", wxid));
		String fmt = "https://api.weixin.qq.com/sns/oauth2/access_token" + "?appid=%s" + "&secret=%s" + "&code=%s"
				+ "&grant_type=authorization_code";

		String url = String.format(fmt, config.getString("appid"), config.getString("appsecret"), code);
		String json = Http.get(url).getContent();
		NutMap map = Json.fromJson(NutMap.class, json);
		String openid = map.getString("openid");
		WxApi2 wxApi2 = getWxApi2(config);
		Record usr = dao.fetch("users", Cnd.where("openid", "=", openid).and("wxid", "=", wxid));
		WxResp resp = wxApi2.user_info(openid, "zh_CN");
		if (usr == null) {
			usr = Json.fromJson(Record.class, Json.toJson(resp.user()));
			if (usr != null && usr.getString("nickname") != null) {
				usr.set("nickname", Strings.sNull(
						EmojiParser.parseToAliases(usr.getString("nickname"), EmojiParser.FitzpatrickAction.REMOVE)));
				usr.set("subscribeat", (resp.user().getSubscribe_time()));
				usr.set("wxid", wxid);
				usr.set(".table", "users");
				dao.insert(usr);
			}
		} else {
			String id = usr.getString("id");
			usr = Json.fromJson(Record.class, Json.toJson(resp.user()));
			usr.set("nickname",
					EmojiParser.parseToAliases(usr.getString("nickname"), EmojiParser.FitzpatrickAction.REMOVE));
			usr.set("opat", (int) (System.currentTimeMillis() / 1000));
			usr.set("wxid", wxid);
			usr.set("id", id);
			usr.set(".table", "users");
			dao.updateIgnoreNull(usr);
		}
		session.setAttribute("wxid", wxid);
		session.setAttribute("openid", usr.get("openid"));
		return "redirect:" + wechat_goto_url;
	}

	private WxApi2 getWxApi2(Record appInfo) {
		DaoAccessTokenStore myDaoAccessTokenStore = new DaoAccessTokenStore(dao);
		Map<String, Object> params = new HashMap<>();
		params.put("id", appInfo.getString("id"));
		myDaoAccessTokenStore.setTableAccessToken("access_token");
		myDaoAccessTokenStore.setTableAccessTokenExpires("access_token_expires");
		myDaoAccessTokenStore.setTableAccessTokenLastat("access_token_lastat");
		myDaoAccessTokenStore
				.setFetch("select access_token,access_token_expires,access_token_lastat from wx_config where id=@id");
		myDaoAccessTokenStore.setUpdate(
				"update wx_config set access_token=@access_token, access_token_expires=@access_token_expires, access_token_lastat=@access_token_lastat where id=@id");
		myDaoAccessTokenStore.setParams(params);
		WxApi2Impl wxApi2 = new WxApi2Impl();
		wxApi2.setAppid(appInfo.getString("appid"));
		wxApi2.setAppsecret(appInfo.getString("appsecret"));
		wxApi2.setEncodingAesKey(appInfo.getString("encoding_aes_key"));
		wxApi2.setToken(appInfo.getString("access_token"));
		wxApi2.setAccessTokenStore(myDaoAccessTokenStore);
		return wxApi2;
	}

}
